/**
 * @file mutex.c
 * @author lcz (you@domain.com)
 * @brief 
 * @version 0.1
 * @date 2022-10-23
 * 
 * @copyright Copyright (c) 2022
 * 
 */

#include "ipc/mutex.h"
#include "cpu/irq.h"
/**
 * 锁初始化
 */
void mutex_init(mutex_t *mutex){
    mutex->owner = (task_t *)0;
    mutex->locked_count = 0;
    list_init(&(mutex->wait_list));
}
/**
 * 申请锁
 */
void mutex_lock(mutex_t *mutex){
    irq_state_t state = irq_enter_protection();
    task_t *curr=task_current();
    if (mutex->locked_count==0)
    {
        mutex->locked_count++;
        mutex->owner=curr;
    }
    else if (mutex->owner==curr){
        // mutex->locked_count++;
    }else {
        mutex->locked_count++;
        task_set_block(curr);
        list_insert_last(&(mutex->wait_list), &(curr->wait_node));
        task_dispatch();
    }

    irq_leave_protection(state);
}
/**
 * 释放锁
 */
void mutex_unlock(mutex_t *mutex){
    irq_state_t state = irq_enter_protection();
    task_t * curr=task_current();
    if (mutex->owner==curr)
    {
        mutex->locked_count--;
        // 最后一个用锁的进程
        if (mutex->locked_count==0)
        {
            mutex->owner=(task_t*)0;
        }else{
            // 再判断一下是否还有要锁的人
            if (list_count(&(mutex->wait_list)))
            {
            //   将队首进程加入到就绪队列
            list_node_t *node = list_remove_first(&(mutex->wait_list));
            task_t* task =list_node_parent(node,task_t,wait_node);
            task_set_ready(task);
            // 加入就绪队列后锁归该进程所有，重新加入就绪队列，下次被调度就该
            // 次进程拥有锁进入临界资源了，希望有用 :)
            mutex->owner=task;
            task_dispatch();
            }
            
        }
        
    }

    irq_leave_protection(state);
}
